package cn.minimelon.solon.service.system.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.minimelon.solon.domain.system.FusionOutBalanceDetail;
import cn.minimelon.solon.domain.system.FusionOutBalanceDetailVO;
import cn.minimelon.solon.domain.system.FusionQueryVO;
import cn.minimelon.solon.mapper.system.CompanyInfoMapper;
import cn.minimelon.solon.mapper.system.FusionOutBalanceMapper;
import cn.minimelon.solon.mapper.system.Spd2OutBalanceMapper;
import cn.minimelon.solon.service.system.Spd2DistrService;
import cn.minimelon.solon.service.system.thread.ExcelHandler;
import lombok.extern.slf4j.Slf4j;
import org.beetl.sql.solon.annotation.Db;
import org.noear.solon.annotation.Component;
import org.noear.solon.data.annotation.Tran;
import org.noear.solon.data.tran.TranPolicy;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Component("spd2DistrService")
public class Spd2DistrServiceImpl implements Spd2DistrService {
    private static final Integer PAGE_SIZE = 20000;
    private static final Map<String, String> compNameMap = new HashMap<>();

    @Db("master")
    private Spd2OutBalanceMapper spd2OutBalanceMapper;

    @Db("master")
    private CompanyInfoMapper companyInfoMapper;

    @Db("writer")
    private FusionOutBalanceMapper fusionOutBalanceMapper;

    @Override
    public Integer initFusionDetail(FusionQueryVO query) {
        ExcelHandler<Integer> handler = new ExcelHandler<>(query.getYear(), "spd2DistrService");
        handler.multiThreadWrite();
        return 0;
    }

    @Override
    public void insertMonthRangeSplit(DateTime startTime, DateTime endTime, String month) {
        FusionQueryVO query = new FusionQueryVO();
        query.setStartTime(DateUtil.formatDateTime(startTime));
        query.setEndTime(DateUtil.formatDateTime(endTime));
        query.setMonth(month);
        query.setPageSize(PAGE_SIZE);
        Integer count1 = spd2OutBalanceMapper.selectCountByCond(query);
        Integer count2 = fusionOutBalanceMapper.selectCountByCond(query);
        log.error("结算月：{} 数据量:{}~{} 时间:{}~{}", query.getMonth(), count1, count2, query.getStartTime(), query.getEndTime());
        if (count1 > count2) {
            int pageSize = BigDecimal.valueOf(count1).divide(BigDecimal.valueOf(PAGE_SIZE), RoundingMode.CEILING).intValue();
            for (int i = 0; i < pageSize; i++) {
                try {
                    query.setSkip(i * PAGE_SIZE);
                    List<FusionOutBalanceDetailVO> detailList = spd2OutBalanceMapper.selectListByCond(query);
                    if (CollUtil.isNotEmpty(detailList)) {
                        log.info(">>>>> 数量 {}, 开始执行", detailList.size());
                        List<List<FusionOutBalanceDetailVO>> groupList = ListUtil.split(detailList, 1000);
                        insertSplitGroup(groupList);
                        log.info(">>>>> 数量 {}, 结束", detailList.size());
                    }
                } catch (Exception ex) {
                    ex.printStackTrace();
                    log.error("错误时间段：{}~{} 页数:{}, msg:{}", query.getStartTime(), query.getEndTime(), i, ex.getMessage());
                }
            }
        }
    }

    @Tran(policy = TranPolicy.requires_new)
    public void insertSplitGroup(List<List<FusionOutBalanceDetailVO>> groupList) {
        for (List<FusionOutBalanceDetailVO> group : groupList) {
            insertFusionDistrDetail(group);
        }
    }

    @Tran
    public void insertFusionDistrDetail(List<FusionOutBalanceDetailVO> detailList) {
        List<String> idList = detailList.stream().map(FusionOutBalanceDetailVO::getDetailId).collect(Collectors.toList());
        List<String> existList = fusionOutBalanceMapper.selectByDetailIds(idList);
        List<FusionOutBalanceDetailVO> newList = detailList.stream()
                .filter(it -> !existList.contains(it.getDetailId()))
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(newList)) {
            return;
        }
        for (FusionOutBalanceDetailVO detail : newList) {
            detail.setId(String.valueOf(IdUtil.getSnowflakeNextId()));
            detail.setVersion(0);
            detail.setCreateUser("0000");
            if (detail.getCreateTime() == null) {
                detail.setCreateTime(detail.getOperationTime());
            }
            detail.setLastModified(new Date());
            detail.setLastModifiedUser("0000");
            detail.setHosVersion(2);
            if (StrUtil.isNotEmpty(detail.getMfrsId()) && StrUtil.isEmpty(detail.getMfrsName())) {
                detail.setMfrsName(getCompName(detail.getMfrsId()));
            }
        }
        List<FusionOutBalanceDetail> list = new ArrayList<>(newList);
        fusionOutBalanceMapper.insertBatch(list);
    }

    public void insertFusionDistrDetailSingle(List<FusionOutBalanceDetailVO> detailList) {
        for (FusionOutBalanceDetailVO detail : detailList) {
            int count = fusionOutBalanceMapper.selectCountByDetailId(detail.getDetailId());
            if (count > 0) {
                continue;
            }
            detail.setId(String.valueOf(IdUtil.getSnowflakeNextId()));
            detail.setVersion(0);
            detail.setCreateUser("0000");
            detail.setLastModified(new Date());
            detail.setLastModifiedUser("0000");
            detail.setHosVersion(2);
            if (StrUtil.isNotEmpty(detail.getMfrsId()) && StrUtil.isEmpty(detail.getMfrsName())) {
                detail.setMfrsName(getCompName(detail.getMfrsId()));
            }
            fusionOutBalanceMapper.insert(detail);
        }
    }

    public String getCompName(String id) {
        String name = compNameMap.get(id);
        if (StrUtil.isEmpty(name)) {
            name = companyInfoMapper.selectCompNameById(id);
            compNameMap.put(id, name);
        }
        return name;
    }
}
